#!/usr/bin/python2.5

"""Defines common geo math functions used throughout the library."""

import math

import geotypes

RADIUS = 6378135


def distance(p1, p2):
  """Calculates the great circle distance between two points (law of cosines).

  Args:
    p1: A geotypes.Point or db.GeoPt indicating the first point.
    p2: A geotypes.Point or db.GeoPt indicating the second point.

  Returns:
    The 2D great-circle distance between the two given points, in meters.
  """
  p1lat, p1lon = math.radians(p1.lat), math.radians(p1.lon)
  p2lat, p2lon = math.radians(p2.lat), math.radians(p2.lon)
  
  tmp = math.sin(p1lat) * math.sin(p2lat) + math.cos(p1lat) * math.cos(p2lat) * math.cos(p2lon - p1lon)
  tmp = min(tmp, 1) # accracy problem, tmp is sometimes 1.00000243
  return RADIUS * math.acos(tmp)


def isPointOnLine(point, start, end):
    
    a = distance(point, start)
    b = distance(point, end)
    c = distance(start, end)
    
    # Law of cosines
    # http://en.wikipedia.org/wiki/Law_of_cosines
    def angleByLawOfCos(a, b, c): 
        tmp = (a**2 + b**2 - c**2)/(2*a*b)
        tmp = min(tmp, 1)  # accracy problem, tmp is sometimes 1.00000243
        return math.acos(tmp)
    
    if a == 0 or b == 0:
        return True
    
    try:
        a_ang = angleByLawOfCos(b, c, a)
        b_ang = angleByLawOfCos(a, c, b)
    except ValueError:
        raise Exception("(a,b,c) = (%f, %f, %f)" % (a,b,c))
    
    return a_ang < 90 and b_ang < 90
